package org.huaxi.spring.support;

import org.huaxi.annotation.DynamicDS;
import org.huaxi.core.DSAnnotationInfo;
import org.huaxi.internal.DSConfigurationExtractor;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.StringValueResolver;

import java.lang.reflect.Method;
import java.util.Optional;

/**
 * Created by huwei on 2019/5/10.
 */
public class SpringDSConfigurationExtractor implements DSConfigurationExtractor {

  private StringValueResolver embeddedValueResolver;

  public SpringDSConfigurationExtractor() {
  }

  public SpringDSConfigurationExtractor(StringValueResolver embeddedValueResolver) {
    this.embeddedValueResolver = embeddedValueResolver;
  }

  @Override
  public Optional<DSAnnotationInfo> getDsAnnotationInfo(Object target, Method method) {
    DynamicDS dynamicDS = findAnnotation(target, method);
    if (dynamicDS != null) {
      return Optional.of(getDSAnnotationInfo(dynamicDS));
    }
    return Optional.empty();
  }

  private DSAnnotationInfo getDSAnnotationInfo(DynamicDS dynamicDS) {
    if (embeddedValueResolver == null) {
      return new DSAnnotationInfo(dynamicDS.value());
    }
    return new DSAnnotationInfo(embeddedValueResolver.resolveStringValue(dynamicDS.value()));
  }

  DynamicDS findAnnotation(Object target, Method method) {
    DynamicDS annotation = findAnnotation(method);
    if (annotation != null) {
      return annotation;
    } else {
      Class<?> targetClass = AopUtils.getTargetClass(target);
      if (targetClass != null) {
        try {
          Method methodOnTarget = targetClass
                  .getMethod(method.getName(), method.getParameterTypes());
          return findAnnotation(methodOnTarget);
        } catch (NoSuchMethodException e) {
          return null;
        }
      } else {
        return null;
      }
    }
  }

  DynamicDS findAnnotation(Method method) {
    return AnnotatedElementUtils.getMergedAnnotation(method, DynamicDS.class);
  }
}
